package com.zhaotianhao.check.comboserver.common;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.util.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class PDFUtils {


	/*
	 PDFUtils.table2pdf("D://pic/house.pdf",null,
                "房子信息统计", Arrays.asList("编号","房主","坐落地址"),
                Arrays.asList("houseId","ownerNames","houseAddress"),info.getList(),null);
	 */

    /**
     * 把table转成PDF
     *
     * @param path      生成的pdf存放的路径和名称   d://pic/user.pdf
     * @param font      生成文字的字体 ,如果不设置,使用默认
     * @param title     标题
     * @param hreders   表格头   首行
     * @param props     属性名(获得对象中那些属性的值生成pdf表格)
     * @param list      数据(从数据库查询的数据)
     * @param imagePath PDF中存放图片
     * @param <T>
     */
    public static <T> void table2pdf(String path, Font font,String imagePath, String title,
                                     List<String> hreders,List<String> props, List<T> list) throws Exception {


        try {
        //1.新建document对象，
        Document document = new Document();
        OutputStream os = new FileOutputStream(new File(path));

        //2.建立一个书写器(Writer)与document对象关联，通过书写器(Writer)可以将文档写入到磁盘中
        PdfWriter.getInstance(document, os);

        //3.打开文档
        document.open();


        //4.向文档中添加内容
        //--------------------------------------

        //设置字体
        if (font == null) {
            BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            font = new Font(bfChinese);
        }


        //写入标题 header

        if (title != null && !"".equals(title)) {
            writeHeader(font, title, document);
        }

        //写入数据   写入表格
        if (hreders != null && hreders.size() > 0) {
            PdfPTable table = new PdfPTable(hreders.size());
            for (String string : hreders) {
                table.addCell(new PdfPCell(new Paragraph(string, font)));
            }

            //加入数据
            writerTableContent(font, props, list, table);


            document.add(table);

        }


        //写入图片
        writeImage(imagePath, document);


        document.close();
        System.err.println("-----------pdf导出成功---------");
        } catch (Exception e) {
        // TODO Auto-generated catch block
        //e.printStackTrace();
        System.err.println("-----------pdf导出失败---------");

        }


    }


    //----------------------------------------------------

    /**
     * pdf转图片
     *
     * @param pdfFile
     * @param pngFile
     * @return
     */
    public static boolean pdf2png(String pdfFile, String pngFile) {
        System.out.println("开始pdf生成png图片");
        try {
            // 加载pdf信息
            PDDocument pdfDocment = PDDocument.load(new File(pdfFile));
            // 获取页数
            int pages = pdfDocment.getNumberOfPages();
            // 获取pdf渲染
            PDFRenderer pdfRenderer = new PDFRenderer(pdfDocment);
            // 循环转化
            for (int i = 0; i < pages; i++) {
                BufferedImage image = pdfRenderer.renderImageWithDPI(i, 144);// page , dpi分辨率单位
                // BufferedImage image = renderer.renderImage(i, 2.5f); // 也可以 page,缩放比
                ImageIO.write(image, "PNG", new File(pngFile));
//	            ImageIO.write(image, "PNG", 
//	            		new File(new StringBuffer(pngFile).insert(pdfFile.lastIndexOf("."),"_"+i ).toString()));
                System.out.println("生成成功");
            }

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("转化失败");
            return false;
        }
        return true;
    }

    //----------------------------------------------------

    //添加文本水印

    /**
     * 添加水印
     *
     * @param is       输入流  本来的pdf
     * @param os       输出流 加水印后的pdf
     * @param mainMark 主文本(水印内容)
     * @param rootMark 页脚文本(水印内容)
     * @throws DocumentException
     * @throws IOException
     */
    public static void markTxt(InputStream is, OutputStream os, String mainMark, String rootMark)
            throws DocumentException, IOException {
        markTxt(0.5f, 60, true, is, os, mainMark, rootMark);
    }

    /**
     * @param alpha    透明度 0-1
     * @param degree   角度 0-360
     * @param isUnder  水印置于文本上/下
     * @param is       输入IO
     * @param os       输出IO
     * @param mainMark 主文本(水印内容)
     * @param rootMark 页脚文本(水印内容)
     */
    private static void markTxt(float alpha, int degree, boolean isUnder, InputStream is, OutputStream os,
                                String mainMark, String rootMark) throws DocumentException, IOException {
        PdfReader reader = new PdfReader(is);
        //用来签署pdf文件
        PdfStamper stamper = new PdfStamper(reader, os);

        try {
            PdfGState gs = new PdfGState();
            gs.setFillOpacity(alpha);//设置透明度为0.5

            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);


            PdfContentByte content;
            int total = reader.getNumberOfPages() + 1;
            for (int i = 1; i < total; i++) {
                if (isUnder) {
                    content = stamper.getUnderContent(i);
                } else {
                    content = stamper.getOverContent(i);
                }
                content.setGState(gs);//
                content.beginText();
                content.setColorFill(BaseColor.BLUE);
                content.setFontAndSize(base, 50);
                content.setTextMatrix(70, 200);
                content.showTextAligned(Element.ALIGN_CENTER, mainMark, 300, 350, degree);

                content.setColorFill(BaseColor.GREEN);
                content.setFontAndSize(base, 18);
                content.showTextAligned(Element.ALIGN_CENTER, rootMark, 300, 300, 0);
                content.endText();

            }
        } finally {
            stamper.close();
            reader.close();
            is.close();
        }
    }

//----------------------------------------

    /**
     * 加图片水印
     *
     * @param iconPath
     * @param is
     * @param os
     * @param rootMark
     * @throws DocumentException
     * @throws IOException
     */
    public static void markImage(String iconPath, InputStream is, OutputStream os, String rootMark)
            throws DocumentException, IOException {
        markImage(iconPath, 0.5f, 60, false, is, os, rootMark);
    }

    /**
     * @param iconPath 图标
     * @param alpha    透明度
     * @param degree   角度
     * @param isUnder  在内容下/上方加水印
     * @param is       输入IO
     * @param os       输出IO
     * @param rootMark 页脚文本描述
     */

    private static void markImage(String iconPath, float alpha, int degree, boolean isUnder, InputStream is,
                                  OutputStream os, String rootMark) throws DocumentException, IOException {
        PdfReader reader = new PdfReader(is);
        // 关联源文件和目标文件
        PdfStamper stamper = new PdfStamper(reader, os);
        try {
            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);

            PdfGState gs = new PdfGState();
            gs.setFillOpacity(alpha);

            PdfContentByte content;
            // 获取页数 遍历 加水印
            for (int i = 1; i <= reader.getNumberOfPages(); i++) {
                if (isUnder) {
                    content = stamper.getUnderContent(i);
                } else {
                    content = stamper.getOverContent(i);
                }

                content.setGState(gs);
                content.beginText();

                Image image = Image.getInstance(iconPath);
                image.setAlignment(Image.LEFT | Image.TEXTWRAP);
                image.setRotationDegrees(degree);
                image.setAbsolutePosition(200, 200);
                image.scaleToFit(200, 200);

                content.addImage(image);
                content.setColorFill(BaseColor.BLACK);
                content.setFontAndSize(base, 8);
                content.showTextAligned(Element.ALIGN_CENTER, rootMark, 300, 300, 0);
                content.endText();
            }
        } finally {
            stamper.close();
            reader.close();
            is.close();
        }
    }


    public static void writeImage(String imagePath, Document document)
            throws BadElementException, MalformedURLException, IOException, DocumentException {
        if (imagePath != null && !"".equals(imagePath)) {
            Image instance = Image.getInstance(imagePath);
            instance.setAlignment(Image.ALIGN_CENTER);
            instance.scalePercent(40);// 依照比例缩放
            document.add(instance);
        }


    }

    public static <T> void writerTableContent(Font font, List<String> props, List<T> list, PdfPTable table)
            throws Exception {
        for (T t : list) {//循环数据

            for (String fieldName : props) {//循环需要获得的属性名
                Field field = t.getClass().getDeclaredField(fieldName);
                if (field != null) {
                    //打破封装
                    field.setAccessible(true);
                    //获得属性值
                    Object value = field.get(t);
                    //如果value的真实的类型是Date类型   生成pdf的时候 指定格式
                    if (value != null) {
                        if (value instanceof Date) {
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                            table.addCell(new PdfPCell(new Paragraph(sdf.format(value), font)));
                        }else {
                            table.addCell(new PdfPCell(new Paragraph(value.toString(), font)));

                        }
                    } else {
                        table.addCell(new PdfPCell(new Paragraph("", font)));
                    }
                }else{
                    table.addCell(new PdfPCell(new Paragraph("", font)));
                }
            }
        }

    }

    //写入标题
    public static void writeHeader(Font font, String title, Document document) throws DocumentException {
        // 添加段落// 如果不设置字体,中文写入不上
        Paragraph paragraph = new Paragraph(title, font);
        paragraph.setAlignment(1); // 设置文字居中 0靠左 1，居中 2，靠右
        paragraph.setIndentationLeft(12); // 设置左缩进
        paragraph.setIndentationRight(12); // 设置右缩进
        paragraph.setFirstLineIndent(24); // 设置首行缩进
        paragraph.setLeading(20f); // 行间距
        paragraph.setSpacingBefore(5f); // 设置段落上空白
        paragraph.setSpacingAfter(10f); // 设置段落下空白
        document.add(paragraph);
    }





    //如果数据中存在图片,则使用这个

    public static <T> void tableAndImg2pdf(String path, Font font,String imagePath,String title,
                                     List<String> hreders,PDFWriter writer) throws Exception {

        try {
            // 字体
            if (font == null) {
                BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                font = new Font(bfChinese);
            }

            // 1.创建document对象 默认页面大小是A4
            Document document = new Document();
            // 2.建立一个书写器(Writer)与document对象关联，通过书写器(Writer)可以将文档写入到磁盘中
            // 并指定生成的pdf的位置
            PdfWriter.getInstance(document, new FileOutputStream(new File(path)));

            // 2.打开文档
            document.open();
            // 4.写入文档头 //StringUtils 是spring提供的工具栏
            if (!StringUtils.isEmpty(title)) {
                writeHeader(font, title, document);

            }

            //加入表格
            PdfPTable table = new PdfPTable(hreders.size());
            for (String string : hreders) {
                table.addCell(new PdfPCell(new Paragraph(string, font)));
            }
            //写入内容(使用接口的抽象方法,调用者自己手动存值)
            writer.execute(table,font);


            document.add(table);

            // 写入图片
            if (!StringUtils.isEmpty(imagePath)) {
                writeImage(imagePath, document);
            }

            document.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

    }


    public interface PDFWriter{
        void execute(PdfPTable pdfPTable, Font font) throws BadElementException, IOException;
    }

    /*教程
    List<Combo> list = iComboService.list();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    String fileName = "d:/pic/combo.pdf";
    PDFUtils.tableAndImg2pdf(fileName, null,
            null, "套餐列表",
            Arrays.asList("ID", "套餐名", "套餐助记码", "价格", "图片"), new PDFUtils.PDFWriter() {
        @Override
        public void execute(PdfPTable pdfPTable, Font font) throws BadElementException, IOException {
            for (Combo combo : list) {
                pdfPTable.addCell(new PdfPCell(new Paragraph(combo.getId()+"",font)));
                pdfPTable.addCell(new PdfPCell(new Paragraph(combo.getComboName()+"",font)));
                pdfPTable.addCell(new PdfPCell(new Paragraph(combo.getComboCoding()+"",font)));
                pdfPTable.addCell(new PdfPCell(new Paragraph(combo.getPrice()+"",font)));
                pdfPTable.addCell(Image.getInstance(combo.getImg()));
            }
        }
    });
    String path = UUID.randomUUID().toString() + ".pdf";

    PDFUtils.markImage("D:/pic/1.jpg",
            new FileInputStream(fileName),
            new FileOutputStream("d:/pic/"+path),"版权");
    return JsonResult.successd(path);*/


}

